<?php

namespace app\upload\controller;

use uploadImg\imgcompress;

class UploadFile
{
    // 后台上传图片（压缩）
    public function uploadPicture()
    {
        /* 返回标准数据 */
        $return = ['status' => 1, 'info' => '上传成功', 'data' => ''];

        // 检查文件是否存在
        if (!isset($_FILES['download']) || $_FILES['download']['error'] !== UPLOAD_ERR_OK) {
            $return['status'] = 2;
            $return['msg'] = '文件上传失败';
            return json($return);
        }

        $dir = './uploads/Picture/' . date('Ymd');
        if (!is_dir($dir)) mkdir($dir);

        $source = $_FILES['download']['tmp_name'];
        $type = $_FILES['download']['type'];
        $name = $_FILES['download']['name'];

        // 允许的扩展名
        $allowed_ext = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
        $ext = strtolower(pathinfo($name, PATHINFO_EXTENSION));
        if (!in_array($ext, $allowed_ext)) {
            $return['status'] = 2;
            $return['msg'] = '不允许的图片格式';
            return json($return);
        }

        // MIME 类型检测
        $allowed_mime = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $mime = finfo_file($finfo, $source);
        finfo_close($finfo);
        if (!in_array($mime, $allowed_mime)) {
            $return['status'] = 2;
            $return['msg'] = '非法图片类型';
            return json($return);
        }

        // 用 getimagesize 再次确认是图片
        $img_info = @getimagesize($source);
        if ($img_info === false) {
            $return['status'] = 2;
            $return['msg'] = '文件不是有效的图片';
            return json($return);
        }

        $save_img = $dir . '/' . uniqid() . '.' . explode('/', $type)[1];
        $percent = 1;
        $obj = new imgcompress($source, $percent);

        $picture = model('Picture');
        $hash['md5'] = md5_file($source);
        $hash['sha1'] = sha1_file($source);
        $picture_id = $picture->field(true)->where($hash)->value("id");

        if (empty($picture_id)) {
            $res = $obj->compressImg($save_img);
            if ($res) {
                $data = [
                    'path' => substr($save_img, 1),
                    'md5' => $hash['md5'],
                    'sha1' => $hash['sha1'],
                    'create_time' => time()
                ];
                $picture_id = $picture->insertGetId($data);
            }
        }

        $info = $picture->field("id,path")->where(["id" => $picture_id])->find();
        if ($info) {
            $return['status'] = 1;
            $return['data'] = $info;
        } else {
            $return['status'] = 0;
            $return['info'] = model('Picture')->getError();
        }

        $obj->__destruct();

        return json($return);
    }

    // uni-app 上传图片
    public function uniUploadPicture()
    {
        //        Loader::import('uploadImg\imgcompress', EXTEND_PATH);

        /* 返回标准数据 */
        $return = ['result' => 1, 'msg' => '上传成功', 'data' => ''];

        // 检查文件是否存在
        if (!isset($_FILES['download']) || $_FILES['download']['error'] !== UPLOAD_ERR_OK) {
            $return['status'] = 2;
            $return['msg'] = '文件上传失败';
            return json($return);
        }

        $dir = './uploads/Picture/' . date('Ymd');
        if (!is_dir($dir)) mkdir($dir);

        $source = $_FILES['download']['tmp_name'];
        $name = $_FILES['download']['name'];

        // 允许的扩展名
        $allowed_ext = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
        $ext = strtolower(pathinfo($name, PATHINFO_EXTENSION));
        if (!in_array($ext, $allowed_ext)) {
            $return['status'] = 2;
            $return['msg'] = '不允许的图片格式';
            return json($return);
        }

        // MIME 类型检测
        $allowed_mime = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $mime = finfo_file($finfo, $source);
        finfo_close($finfo);
        if (!in_array($mime, $allowed_mime)) {
            $return['status'] = 2;
            $return['msg'] = '非法图片类型';
            return json($return);
        }

        // 用 getimagesize 再次确认是图片
        $img_info = @getimagesize($source);
        if ($img_info === false) {
            $return['status'] = 2;
            $return['msg'] = '文件不是有效的图片';
            return json($return);
        }

        $save_img = $dir . '/' . uniqid() . '.' . pathinfo($name, PATHINFO_EXTENSION);
        $percent = 1;

        $obj = new imgcompress($source, $percent);

        $picture = model('Picture');
        $hash['md5'] = md5_file($source);
        $hash['sha1'] = sha1_file($source);
        $picture_id = $picture->field(true)->where($hash)->value("id");

        if (empty($picture_id)) {
            $res = copy($source, $save_img);

            if ($res) {
                $data = [
                    'path' => substr($save_img, 1),
                    'md5' => $hash['md5'],
                    'sha1' => $hash['sha1'],
                    'create_time' => time()
                ];
                $picture_id = $picture->insertGetId($data);
            }
        }

        $info = $picture->field("id,path")->where(["id" => $picture_id])->find();
        $info['path'] = getHost() . $info['path'];

        if ($info) {
            $return['status'] = 1;
            $return['data'] = $info;
        } else {
            $return['status'] = 2;
            $return['msg'] = '图片上传失败';
        }

        $obj->__destruct();

        return json($return);
    }

    // 上传图片保留透明层
    public function uploadPictureKeepLucency()
    {
        // Loader::import('uploadImg\imgcompress', EXTEND_PATH);

        /* 返回标准数据 */
        $return = ['status' => 1, 'info' => '上传成功', 'data' => ''];

        // 检查文件是否存在
        if (!isset($_FILES['download']) || $_FILES['download']['error'] !== UPLOAD_ERR_OK) {
            $return['status'] = 2;
            $return['msg'] = '文件上传失败';
            return json($return);
        }

        $dir = './uploads/Picture/' . date('Ymd');
        if (!is_dir($dir)) mkdir($dir);

        $source = $_FILES['download']['tmp_name'];
        $name = $_FILES['download']['name'];
        $save_img = $dir . '/' . uniqid() . '.' . pathinfo($name, PATHINFO_EXTENSION);
        $percent = 1;

        // 允许的扩展名
        $allowed_ext = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
        $ext = strtolower(pathinfo($name, PATHINFO_EXTENSION));
        if (!in_array($ext, $allowed_ext)) {
            $return['status'] = 2;
            $return['msg'] = '不允许的图片格式';
            return json($return);
        }

        // MIME 类型检测
        $allowed_mime = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $mime = finfo_file($finfo, $source);
        finfo_close($finfo);
        if (!in_array($mime, $allowed_mime)) {
            $return['status'] = 2;
            $return['msg'] = '非法图片类型';
            return json($return);
        }

        // 用 getimagesize 再次确认是图片
        $img_info = @getimagesize($source);
        if ($img_info === false) {
            $return['status'] = 2;
            $return['msg'] = '文件不是有效的图片';
            return json($return);
        }

        $obj = new imgcompress($source, $percent);

        $picture = model('Picture');
        $hash['md5'] = md5_file($source);
        $hash['sha1'] = sha1_file($source);
        $picture_id = $picture->field(true)->where($hash)->value("id");

        if (empty($picture_id)) {
            $res = $obj->uploadImgKeepLucency($save_img);
            if ($res) {
                $data = [
                    'path' => substr($save_img, 1),
                    'md5' => $hash['md5'],
                    'sha1' => $hash['sha1'],
                    'create_time' => time()
                ];
                $picture_id = $picture->insertGetId($data);
            }
        }

        $info = $picture->field("id,path")->where(["id" => $picture_id])->find();
        if ($info) {
            $return['status'] = 1;
            $return['data'] = $info;
        } else {
            $return['status'] = 0;
            $return['info'] = model('Picture')->getError();
        }

        $obj->__destruct();

        return json($return);
    }

    // 规格-属性 上传图片
    public function uploadSkuPicture()
    {
        // Loader::import('uploadImg\imgcompress', EXTEND_PATH);

        /* 返回标准数据 */
        $return = ['code' => 200, 'msg' => '上传成功', 'data' => []];

        // 检查文件是否存在
        if (!isset($_FILES['download']) || $_FILES['download']['error'] !== UPLOAD_ERR_OK) {
            $return['status'] = 2;
            $return['msg'] = '文件上传失败';
            return json($return);
        }

        $dir = './uploads/Picture/' . date('Ymd');
        if (!is_dir($dir)) mkdir($dir);

        $source = $_FILES['download']['tmp_name'];
        $name = $_FILES['download']['name'];

        // 允许的扩展名
        $allowed_ext = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
        $ext = strtolower(pathinfo($name, PATHINFO_EXTENSION));
        if (!in_array($ext, $allowed_ext)) {
            $return['status'] = 2;
            $return['msg'] = '不允许的图片格式';
            return json($return);
        }

        // MIME 类型检测
        $allowed_mime = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $mime = finfo_file($finfo, $source);
        finfo_close($finfo);
        if (!in_array($mime, $allowed_mime)) {
            $return['status'] = 2;
            $return['msg'] = '非法图片类型';
            return json($return);
        }

        // 用 getimagesize 再次确认是图片
        $img_info = @getimagesize($source);
        if ($img_info === false) {
            $return['status'] = 2;
            $return['msg'] = '文件不是有效的图片';
            return json($return);
        }

        $source = $_FILES['file']['tmp_name'];
        $name = $_FILES['file']['name'];
        $save_img = $dir . '/' . uniqid() . '.' . pathinfo($name, PATHINFO_EXTENSION);
        $percent = 1;
        $obj = new imgcompress($source, $percent);

        $picture = model('Picture');
        $hash['md5'] = md5_file($source);
        $hash['sha1'] = sha1_file($source);
        $picture_id = $picture->field(true)->where($hash)->value("id");

        if (empty($picture_id)) {
            $res = $obj->compressImg($save_img);
            if ($res) {
                $data = [
                    'path' => substr($save_img, 1),
                    'md5' => $hash['md5'],
                    'sha1' => $hash['sha1'],
                    'create_time' => time()
                ];
                $picture_id = $picture->insertGetId($data);
            }
        }

        $info = $picture->field("id,path url")->where(["id" => $picture_id])->find();
        if ($info) {
            $return['code'] = 200;
            $return['data'] = $info;
        } else {
            $return['code'] = 0;
            $return['info'] = model('Picture')->getError();
        }

        return json($return);
    }

    // excel 上传图片
    public function uploadExcelPicture($base64_img, $suffix)
    {
        $hash['md5'] = md5_file($base64_img);
        $hash['sha1'] = sha1_file($base64_img);

        $picture = model('Picture');
        $picture_id = $picture->field(true)->where($hash)->value("id");

        if (empty($picture_id)) {
            $dir = './uploads/Picture/' . date('Ymd');
            if (!is_dir($dir)) mkdir($dir);
            $save_img = $dir . '/' . uniqid() . '.' . $suffix;

            $res = file_put_contents($save_img, file_get_contents($base64_img));
            if ($res) {
                $data = [
                    'path' => substr($save_img, 1),
                    'md5' => $hash['md5'],
                    'sha1' => $hash['sha1'],
                    'create_time' => time()
                ];
                $picture_id = $picture->insertGetId($data);
            }
        }

        return $picture_id;
    }

    // 数据导入上传文件
    public function importUploadFile()
    {
        /* 返回标准数据 */
        $return = ['status' => 1, 'info' => '上传成功', 'data' => ''];

        $error = $_FILES['download']['error'];
        if ($error === 0) {
            $dir = str_replace('\\', '/', getcwd()) . '/uploads/file/' . date('Ymd');
            if (!is_dir($dir)) mkdir($dir);

            $source = $_FILES['download']['tmp_name'];
            $name = $_FILES['download']['name'];
            $save_file = $dir . '/' . $name;

            $res = copy($source, $save_file);

            if ($res) {
                $return['status'] = 0;
                $return['info'] = '文件上传成功，准备导入数据...';
                $return['data'] = $save_file;
            } else {
                $return['status'] = 0;
                $return['info'] = '文件上传失败，请重新选择文件！';
            }
        } else {
            $return['status'] = 0;
            $return['info'] = $error;
        }

        return json($return);
    }

    // 上传文件
    public function uploadFile()
    {
        /* 返回标准数据 */
        $return = ['status' => 1, 'msg' => '上传成功', 'data' => ''];

        $dir = './uploads/file/' . date('Ymd');
        if (!is_dir($dir)) mkdir($dir);

        // name 参数是小程序上传文件传过来的
        $file_name = $_POST['name'];

        $source = $_FILES['download']['tmp_name'];
        $name = $_FILES['download']['name'];
        if ($file_name) {
            $save_path = $dir . '/' . $file_name;
        } else {
            $save_path = $dir . '/' . uniqid() . '.' . pathinfo($name, PATHINFO_EXTENSION);
        }

        $file = model('File');
        $hash['md5'] = md5_file($source);
        $hash['sha1'] = sha1_file($source);
        $file_id = $file->field(true)->where($hash)->value("id");

        if (empty($file_id)) {
            $res = copy($source, $save_path);
            if ($res) {
                $data = [
                    'name' => $file_name,
                    'path' => substr($save_path, 1),
                    'md5' => $hash['md5'],
                    'sha1' => $hash['sha1'],
                    'create_time' => time()
                ];
                $file_id = $file->insertGetId($data);
            }
        }

        $info = $file->field("id,path,name")->where(["id" => $file_id])->find();
        if ($info) {
            $info['name'] = removeFileExtension($info['name']);
            $return['status'] = 1;
            $return['data'] = $info;
        } else {
            $return['status'] = 2;
            $return['msg'] = model('File')->getError();
        }

        return json($return);
    }

    // 上传发票文件
    public function uploadInvoiceFile()
    {
        /* 返回标准数据 */
        $return = ['status' => 1, 'msg' => '上传成功', 'data' => ''];

        $dir = './uploads/file/' . date('Ymd');
        if (!is_dir($dir)) mkdir($dir);

        $allowedExtensions = ['png', 'jpg', 'jpeg', 'pdf'];

        if ($_FILES['download']['error'] === UPLOAD_ERR_OK) {
            // 获取文件的扩展名（不区分大小写）
            $fileExtension = strtolower(pathinfo($_FILES['download']['name'], PATHINFO_EXTENSION));

            // 检查文件扩展名是否在允许的范围内
            if (in_array($fileExtension, $allowedExtensions)) {

                // name 参数是小程序上传文件传过来的
                $file_name = $_POST['name'];

                $source = $_FILES['download']['tmp_name'];
                $name = $_FILES['download']['name'];
                if ($file_name) {
                    $save_path = $dir . '/' . $file_name;
                } else {
                    $save_path = $dir . '/' . uniqid() . '.' . pathinfo($name, PATHINFO_EXTENSION);
                }

                $file = model('File');
                $hash['md5'] = md5_file($source);
                $hash['sha1'] = sha1_file($source);
                $file_id = $file->field(true)->where($hash)->value("id");

                if (empty($file_id)) {
                    $res = copy($source, $save_path);
                    if ($res) {
                        $data = [
                            'name' => $file_name,
                            'path' => substr($save_path, 1),
                            'md5' => $hash['md5'],
                            'sha1' => $hash['sha1'],
                            'create_time' => time()
                        ];
                        $file_id = $file->insertGetId($data);
                    }
                }

                $info = $file->field("id,path,name")->where(["id" => $file_id])->find();
                if ($info) {
                    $info['name'] = removeFileExtension($info['name']);
                    $return['status'] = 1;
                    $return['data'] = $info;
                } else {
                    $return['status'] = 0;
                    $return['info'] = model('File')->getError();
                }

                return json($return);
            } else {
                $return['status'] = 2;
                $return['msg'] = "仅允许上传png, jpg, pdf文件";
                return json($return);
            }
        } else {
            $return['status'] = 2;
            $return['msg'] = "文件上传错误";
            return json($return);
        }
    }

    // WebUploader上传文件
    public function webUploaderUploadFile()
    {
        set_time_limit(5 * 60);
        usleep(5000);
        $targetDir = './uploads/tmp_video';                                 //存放分片临时目录
        $uploadDir = './uploads/Video/' . date('Ymd');                      //分片合并存放目录

        if (!file_exists($targetDir)) {
            mkdir($targetDir, 0777, true);
        }
        if (!file_exists($uploadDir)) {
            mkdir($uploadDir, 0777, true);
        }

        $cleanupTargetDir = true; // 移除旧文件
        $maxFileAge = 5 * 3600;

        if (isset($_REQUEST["name"])) {
            $fileName = $_REQUEST["name"];
        } elseif (!empty($_FILES)) {
            $fileName = $_FILES["file"]["name"];
        } else {
            $fileName = uniqid("file_");
        }
        $oldName = $fileName;

        $fileName = iconv('UTF-8', 'gb2312', $fileName);
        $filePath = $targetDir . '/' . $fileName;

        $chunk = isset($_REQUEST["chunk"]) ? intval($_REQUEST["chunk"]) : 0;
        $chunks = isset($_REQUEST["chunks"]) ? intval($_REQUEST["chunks"]) : 1;

        if ($cleanupTargetDir) {
            if (!is_dir($targetDir) || !$dir = opendir($targetDir)) apiReturn(2, '打开临时目录失败');

            while (($file = readdir($dir)) !== false) {
                $tmpfilePath = $targetDir . '/' . $file;

                if ($tmpfilePath == "{$filePath}_{$chunk}" || $tmpfilePath == "{$filePath}_{$chunk}") {
                    continue;
                }

                if (preg_match('/\.(part|parttmp)$/', $file) && (filemtime($tmpfilePath) < time() - $maxFileAge)) {
                    unlink($tmpfilePath);
                }
            }
            closedir($dir);
        }
        // 打开临时文件
        if (!$out = fopen("{$filePath}_{$chunk}", "wb")) apiReturn(2, '打开输出流失败');

        if (!empty($_FILES)) {
            if ($_FILES["file"]["error"] || !is_uploaded_file($_FILES["file"]["tmp_name"])) apiReturn(2, '无法移动上传的文件');

            // 读取二进制输入流并将其附加到临时文件
            if (!$in = fopen($_FILES["file"]["tmp_name"], "rb")) apiReturn(2, '打开输入流失败');
        } else {
            if (!$in = fopen("php://input", "rb")) apiReturn(2, '打开输入流失败');
        }
        while ($buff = fread($in, 4096)) {
            fwrite($out, $buff);
        }
        fclose($out);
        fclose($in);
        rename("{$filePath}_{$chunk}", "{$filePath}_{$chunk}");

        $index = 0;
        $done = true;
        for ($index = 0; $index < $chunks; $index++) {
            if (!file_exists("{$filePath}_{$index}")) {
                $done = false;
                break;
            }
        }

        if ($done) {
            $pathInfo = pathinfo($fileName);
            $hashStr = substr(md5($pathInfo['basename']), 8, 16);
            $hashName = time() . $hashStr . '.' . $pathInfo['extension'];
            $uploadPath = $uploadDir . '/' . $hashName;
            if (!$out = fopen($uploadPath, "wb")) apiReturn(2, '打开输入流失败');

            // flock($hander,LOCK_EX)文件锁
            if (flock($out, LOCK_EX)) {
                for ($index = 0; $index < $chunks; $index++) {
                    if (!$in = fopen("{$filePath}_{$index}", "rb")) {
                        break;
                    }
                    while ($buff = fread($in, 4096)) {
                        fwrite($out, $buff);
                    }
                    fclose($in);
                    unlink("{$filePath}_{$index}");
                }
                flock($out, LOCK_UN);
            }
            fclose($out);

            $path = substr($uploadPath, 1);

            $data = [
                'path' => $path,
                'create_time' => time()
            ];
            $file_id = model('File')->insertGetId($data);

            $data = [
                'id' => $file_id,
                'path' => $path
            ];

            apiReturn(1, '文件上传成功', $data);
        }

        apiReturn(3, '分片上传成功');
    }

    // 上传视频并异步转换为M3U8格式
    public function uploadVideoToM3U8()
    {
        /* 返回标准数据 */
        $return = ['status' => 1, 'msg' => '上传成功', 'data' => ''];

        // 检查文件是否存在
        if (!isset($_FILES['download']) || $_FILES['download']['error'] !== UPLOAD_ERR_OK) {
            $return['status'] = 2;
            $return['msg'] = '文件上传失败';
            return json($return);
        }

        $source = $_FILES['download']['tmp_name'];
        $name = $_FILES['download']['name'];
        $file_name = isset($_POST['name']) ? $_POST['name'] : $name;

        // 检查文件类型是否为MP4
        $ext = strtolower(pathinfo($name, PATHINFO_EXTENSION));
        if ($ext !== 'mp4') {
            $return['status'] = 2;
            $return['msg'] = '请上传MP4格式的视频';
            return json($return);
        }

        // MIME 类型检测
        $allowed_mime = ['video/mp4', 'application/octet-stream'];
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $mime = finfo_file($finfo, $source);
        finfo_close($finfo);
        if (!in_array($mime, $allowed_mime)) {
            $return['status'] = 2;
            $return['msg'] = '非法视频类型';
            return json($return);
        }

        // 计算文件哈希值，用于检查是否已存在
        $file = model('File');
        $hash['md5'] = md5_file($source);
        $hash['sha1'] = sha1_file($source);

        // 检查是否存在相同的文件（状态为已处理完成）
        /*$existingFile = $file->where([
            'md5' => $hash['md5'],
            'sha1' => $hash['sha1'],
            'status' => 2 // 2: 处理完成
        ])->find();
        
        if ($existingFile) {
            // 文件已存在且处理完成，直接返回已存在的文件信息
            $info = $file->field("id,name")->where(["id" => $existingFile['id']])->find();
            if ($info) {
                $info['status'] = 2; // 处理完成
                $info['process_message'] = '视频已存在且处理完成';
                $return['status'] = 1;
                $return['data'] = $info;
                $return['msg'] = '视频已存在且处理完成，无需重复上传';
            }
            return json($return);
        }*/

        // 创建视频目录
        $videoDir = './uploads/Video/' . date('Ymd');
        if (!is_dir($videoDir)) mkdir($videoDir, 0777, true);

        // 创建M3U8目录
        $m3u8Dir = './uploads/M3U8/' . date('Ymd');
        if (!is_dir($m3u8Dir)) mkdir($m3u8Dir, 0777, true);

        // 移除文件扩展名
        $nameWithoutExt = pathinfo($file_name, PATHINFO_FILENAME);

        // 生成唯一ID
        $uniqueId = uniqid();
        $mp4FilePath = $videoDir . '/' . $uniqueId . '.mp4';
        $m3u8FilePath = $m3u8Dir . '/' . $uniqueId . '.m3u8';

        // 尝试使用FFmpeg压缩视频（保持质量的前提下）
        //        $compressed = $this->compressVideoWithFFmpeg($source, $mp4FilePath);

        // 如果压缩失败，尝试直接复制原文件
        //        if (!$compressed) {
        $res = copy($source, $mp4FilePath);

        if (!$res) {
            $return['status'] = 2;
            $return['msg'] = '视频保存失败';
            return json($return);
        }
        //        }

        // 保存到数据库（状态为处理中）
        $data = [
            'name' => $nameWithoutExt,
            'path' => '', // 暂时为空，转换完成后更新
            'md5' => $hash['md5'],
            'sha1' => $hash['sha1'],
            'create_time' => time(),
            'original_path' => substr($mp4FilePath, 1), // 存储原始MP4文件路径
            'status' => 1, // 1: 处理中, 2: 处理完成, 3: 处理失败
            'process_message' => '视频上传成功，正在转换为M3U8格式...'
        ];

        $file_id = $file->insertGetId($data);

        if (!$file_id) {
            $return['status'] = 2;
            $return['msg'] = '数据保存失败';
            return json($return);
        }

        // 将转换任务添加到延迟队列（使用当前时间，立即执行）
        try {
            $this->addVideoConvertTask($file_id, $mp4FilePath, $m3u8FilePath);
        } catch (\Exception $e) {
            // 记录错误，但不影响用户上传
            file_put_contents(RUNTIME_PATH . '/log/queue_error.log', date('Y-m-d H:i:s') . ' - ' . $e->getMessage() . PHP_EOL, FILE_APPEND);
        }

        // 立即返回成功信息，但告知视频正在处理中
        $info = $file->field("id,name")->where(["id" => $file_id])->find();
        if ($info) {
            $info['status'] = 1; // 处理中
            $info['process_message'] = '视频上传成功，正在转换为M3U8格式...';
            $return['status'] = 1;
            $return['data'] = $info;
            $return['msg'] = '视频上传成功，正在后台转换为M3U8格式，请稍后刷新查看';
        } else {
            $return['status'] = 2;
            $return['msg'] = model('File')->getError();
        }

        return json($return);
    }

    // 添加视频转换任务到队列
    protected function addVideoConvertTask($fileId, $mp4FilePath, $m3u8FilePath)
    {
        // 引入延迟队列类
        $queue = new \delayQueue\DelayQueue('video_convert_queue');

        // 添加任务，时间设为当前时间，立即执行
        $taskData = [
            'file_id' => $fileId,
            'mp4_file_path' => $mp4FilePath,
            'm3u8_file_path' => $m3u8FilePath,
            'create_time' => time()
        ];

        $queue->addTask('video_convert', time(), $taskData);
    }

    /**
     * 使用FFmpeg压缩视频（在不影响质量的前提下）
     * @param string $sourcePath 源视频路径
     * @param string $targetPath 目标视频路径
     * @return bool 压缩是否成功
     */
    protected function compressVideoWithFFmpeg($sourcePath, $targetPath)
    {
        // 检查FFmpeg是否可用
        $ffmpegCmd = 'ffmpeg -version';
        // 针对Windows系统的特殊处理
        if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
            $ffmpegCmd = 'ffmpeg -version 2>&1';
        }

        exec($ffmpegCmd, $output, $returnVar);
        if ($returnVar !== 0) {
            // FFmpeg不可用，记录错误但不影响上传
            file_put_contents(RUNTIME_PATH . '/log/video_compress_error.log', date('Y-m-d H:i:s') . ' - FFmpeg未安装或不可用' . PHP_EOL, FILE_APPEND);
            return false;
        }

        try {
            // 获取原视频的信息，用于确定是否需要压缩
            $probeCmd = "ffprobe -v error -select_streams v:0 -show_entries stream=bit_rate,width,height -of csv=p=0 " . escapeshellarg($sourcePath);
            if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
                $probeCmd = 'ffprobe -v error -select_streams v:0 -show_entries stream=bit_rate,width,height -of csv=p=0 "' . $sourcePath . '" 2>&1';
            }

            exec($probeCmd, $probeOutput, $probeReturn);

            if ($probeReturn === 0 && !empty($probeOutput)) {
                // 解析视频信息
                $videoInfo = explode(',', $probeOutput[0]);
                $bitrate = isset($videoInfo[0]) ? intval($videoInfo[0]) : 0;
                $width = isset($videoInfo[1]) ? intval($videoInfo[1]) : 0;
                $height = isset($videoInfo[2]) ? intval($videoInfo[2]) : 0;

                // 降低压缩触发条件，让更多视频能够被压缩
                // 例如：比特率超过2Mbps或分辨率超过1080p
                // 用户需求：即使是四五十MB大小的视频也能进行压缩
                if ($bitrate > 2000000 || $width > 1920) {
                    // 确定压缩参数，优化压缩效果
                    // crf值从23调整为25，提供更好的压缩率（值越高压缩率越高，质量略降低）
                    // maxrate从2500k降低到2000k，限制最大码率
                    $compressionParams = ' -c:v libx264 -preset medium -crf 25 -maxrate 2000k -bufsize 4000k -c:a aac -b:a 128k';

                    // 如果分辨率过大，可以适当缩放
                    if ($width > 1920) {
                        $compressionParams .= ' -vf "scale=1920:-2"';
                    }

                    // 构建FFmpeg压缩命令
                    if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
                        $compressCmd = "ffmpeg -i \"{$sourcePath}\"{$compressionParams} \"{$targetPath}\" 2>&1";
                    } else {
                        $compressCmd = "ffmpeg -i \"{$sourcePath}\"{$compressionParams} \"{$targetPath}\"";
                    }

                    // 执行压缩命令
                    exec($compressCmd, $compressOutput, $compressReturn);

                    if ($compressReturn === 0 && file_exists($targetPath)) {
                        // 压缩成功
                        file_put_contents(RUNTIME_PATH . '/log/video_compress.log', date('Y-m-d H:i:s') . ' - 视频压缩成功: ' . $targetPath . PHP_EOL, FILE_APPEND);
                        return true;
                    } else {
                        // 压缩失败，记录错误
                        file_put_contents(RUNTIME_PATH . '/log/video_compress_error.log', date('Y-m-d H:i:s') . ' - 视频压缩失败: ' . $compressCmd . ' 错误: ' . implode(PHP_EOL, $compressOutput) . PHP_EOL, FILE_APPEND);
                    }
                } else {
                    // 视频质量已经很好，不需要压缩，直接复制
                    file_put_contents(RUNTIME_PATH . '/log/video_compress.log', date('Y-m-d H:i:s') . ' - 视频质量（' . $bitrate . '|' . $width . '）已经很好，不需要压缩: ' . $sourcePath . PHP_EOL, FILE_APPEND);
                }
            }
        } catch (\Exception $e) {
            // 捕获异常，记录错误
            file_put_contents(RUNTIME_PATH . '/log/video_compress_error.log', date('Y-m-d H:i:s') . ' - 视频压缩异常: ' . $e->getMessage() . PHP_EOL, FILE_APPEND);
        }

        // 压缩失败或不需要压缩
        return false;
    }


    // 获取服务器是否安装了FFmpeg
    public function checkFfmpeg()
    {
        $return = ['status' => 1, 'msg' => 'FFmpeg已安装', 'data' => ''];

        // 检查FFmpeg是否可用
        $ffmpegCmd = 'ffmpeg -version';
        // 针对Windows系统的特殊处理
        if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
            // 在Windows上使用2>&1将stderr重定向到stdout
            $ffmpegCmd = 'ffmpeg -version 2>&1';
        }
        exec($ffmpegCmd, $output, $returnVar);

        if ($returnVar !== 0) {
            $return['status'] = 2;
            $return['msg'] = 'FFmpeg未安装或未添加到系统环境变量中，请先安装FFmpeg并确保其在系统PATH中';
        }

        return json($return);
    }

    // 获取视频处理状态
    public function getVideoStatus()
    {
        $return = ['status' => 1, 'msg' => '获取成功', 'data' => ''];

        $fileId = input('file_id');
        if (empty($fileId)) {
            $return['status'] = 2;
            $return['msg'] = '文件ID不能为空';
            return json($return);
        }

        $file = model('File');
        $videoInfo = $file->field('status, process_message')->where(['id' => $fileId])->find();

        if ($videoInfo) {
            $return['data'] = $videoInfo;
        } else {
            $return['status'] = 2;
            $return['msg'] = '未找到该视频文件';
        }

        return json($return);
    }

    // 获取视频完整信息
    public function getVideoInfo()
    {
        $return = ['status' => 1, 'msg' => '获取成功', 'data' => ''];

        $fileId = input('file_id');
        if (empty($fileId)) {
            $return['status'] = 2;
            $return['msg'] = '文件ID不能为空';
            return json($return);
        }

        $file = model('File');
        $videoInfo = $file->field('id, name, path, status, process_message, original_path')
            ->where(['id' => $fileId])
            ->find();

        if ($videoInfo) {
            $return['data'] = $videoInfo;
        } else {
            $return['status'] = 2;
            $return['msg'] = '未找到该视频文件';
        }

        return json($return);
    }

}